Coverage Report

Created: 2025-05-27 14:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\vk-layer-for-rust\vk-layer-for-rust\vulkan-layer-macros\src\details.rs
Line
Count
Source
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use proc_macro2::TokenStream as TokenStream2;
16
use quote::quote;
17
use std::iter::zip;
18
use syn::{spanned::Spanned, Error, Ident, ImplItem, ItemImpl, Type};
19
20
3
fn snake_case_to_upper_camel_case(input: &str) -> String {
21
3
    let first_char = match input.chars().next() {
22
3
        Some(first) => first,
23
0
        None => return input.to_owned(),
24
    };
25
3
    let first_char = first_char.to_uppercase();
26
3
    let mut res: String = first_char.to_string();
27
41
    for (prev, (cur, next)) in zip(
28
3
        input.chars(),
29
3
        zip(input.chars().skip(1), input.chars().skip(2)),
30
    ) {
31
41
        if cur == '_' && 
next != '_'4
{
32
4
            continue;
33
37
        }
34
37
        if prev == '_' {
35
4
            res.push_str(&cur.to_uppercase().to_string());
36
4
            continue;
37
33
        }
38
33
        res.push(cur);
39
    }
40
3
    res.push(input.chars().last().unwrap());
41
3
    res
42
3
}
43
44
9
pub fn autoinfo(item: &ItemImpl, target_trait: &TokenStream2) -> Result<TokenStream2, Error> {
45
9
    let type_name = item.self_ty.as_ref();
46
9
    let hooked_commands = item.items.iter().filter_map(|item| 
{3
47
3
        let function = if let ImplItem::Fn(function) = item {
48
3
            function
49
        } else {
50
0
            return None;
51
        };
52
3
        let func_name = function.sig.ident.to_string();
53
3
        let enum_variant_name = snake_case_to_upper_camel_case(&func_name);
54
3
        let enum_variant_name = Ident::new(&enum_variant_name, function.span());
55
3
        Some(quote!(::vulkan_layer::LayerVulkanCommand::#enum_variant_name))
56
9
    
}3
);
57
9
    Ok(quote! {
58
9
        impl #target_trait for #type_name {
59
9
            type HooksType = Self;
60
9
            type HooksRefType<'a> = &'a Self;
61
9
62
9
            fn hooked_commands() -> &'static [::vulkan_layer::LayerVulkanCommand] {
63
9
                &[#(#hooked_commands),*]
64
9
            }
65
9
66
9
            fn hooks(&self) -> &Self {
67
9
                self
68
9
            }
69
9
        }
70
9
    })
71
9
}
72
73
1
pub fn declare_introspection_queries_impl(global_type: &Type) -> Result<TokenStream2, Error> {
74
1
    Ok(quote! {
75
1
        #[doc = "# Safety"]
76
1
        #[doc = ""]
77
1
        #[doc = "See valid usage of `vkEnumerateInstanceLayerProperties` at "]
78
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceLayerProperties.html>"]
79
1
        #[deny(unsafe_op_in_unsafe_fn)]
80
1
        #[no_mangle]
81
1
        pub unsafe extern "system" fn vkEnumerateInstanceLayerProperties(
82
1
            property_count: *mut u32,
83
1
            properties: *mut ::ash::vk::LayerProperties
84
1
        ) -> ::ash::vk::Result {
85
1
            // Safe because the caller is supposed to follow the exact same safety requirement.
86
1
            unsafe { #global_type::enumerate_instance_layer_properties(property_count, properties) }
87
1
        }
88
1
89
1
        #[doc = "# Safety"]
90
1
        #[doc = ""]
91
1
        #[doc = "See valid usage of `vkEnumerateInstanceExtensionProperties` at "]
92
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html>"]
93
1
        #[deny(unsafe_op_in_unsafe_fn)]
94
1
        #[no_mangle]
95
1
        pub unsafe extern "system" fn vkEnumerateInstanceExtensionProperties(
96
1
            layer_name: *const ::std::ffi::c_char,
97
1
            property_count: *mut u32,
98
1
            properties: *mut ::ash::vk::ExtensionProperties
99
1
        ) -> ::ash::vk::Result {
100
1
            // Safe because the caller is supposed to follow the exact same safety requirement.
101
1
            unsafe {
102
1
                #global_type::enumerate_instance_extension_properties(
103
1
                    layer_name,
104
1
                    property_count,
105
1
                    properties,
106
1
                )
107
1
            }
108
1
        }
109
1
110
1
        #[doc = "# Safety"]
111
1
        #[doc = ""]
112
1
        #[doc = "See valid usage of `vkEnumerateDeviceLayerProperties` at "]
113
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumerateDeviceLayerProperties.html>"]
114
1
        #[deny(unsafe_op_in_unsafe_fn)]
115
1
        #[no_mangle]
116
1
        pub unsafe extern "system" fn vkEnumerateDeviceLayerProperties(
117
1
            physical_device: ::ash::vk::PhysicalDevice,
118
1
            p_property_count: *mut u32,
119
1
            p_properties: *mut ::ash::vk::LayerProperties,
120
1
        ) -> ::ash::vk::Result {
121
1
            // Safe, because the caller is supposed to follow the exact same safety requirement.
122
1
            unsafe {
123
1
                #global_type::enumerate_device_layer_properties(
124
1
                    physical_device,
125
1
                    p_property_count,
126
1
                    p_properties,
127
1
                )
128
1
            }
129
1
        }
130
1
131
1
        #[doc = "# Safety"]
132
1
        #[doc = ""]
133
1
        #[doc = "See valid usage of `vkEnumerateDeviceLayerProperties` at "]
134
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumerateDeviceLayerProperties.html>"]
135
1
        #[deny(unsafe_op_in_unsafe_fn)]
136
1
        #[no_mangle]
137
1
        pub unsafe extern "system" fn vkEnumerateDeviceExtensionProperties(
138
1
            physical_device: ::ash::vk::PhysicalDevice,
139
1
            p_layer_name: *const ::std::ffi::c_char,
140
1
            p_property_count: *mut u32,
141
1
            p_properties: *mut ::ash::vk::ExtensionProperties,
142
1
        ) -> ::ash::vk::Result {
143
1
            // Safe, because the caller is supposed to follow the exact same safety requirement.
144
1
            unsafe {
145
1
                #global_type::enumerate_device_extension_properties(
146
1
                    physical_device,
147
1
                    p_layer_name,
148
1
                    p_property_count,
149
1
                    p_properties,
150
1
                )
151
1
            }
152
1
        }
153
1
154
1
        #[doc = "# Safety"]
155
1
        #[doc = ""]
156
1
        #[doc = "See valid usage of `vkGetInstanceProcAddr` at "]
157
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetInstanceProcAddr.html>"]
158
1
        #[deny(unsafe_op_in_unsafe_fn)]
159
1
        #[no_mangle]
160
1
        pub unsafe extern "system" fn vkGetInstanceProcAddr(
161
1
            instance: ::ash::vk::Instance,
162
1
            p_name: *const ::std::ffi::c_char,
163
1
        ) -> ::ash::vk::PFN_vkVoidFunction {
164
1
            // Safe, because the caller is supposed to follow the exact same safety requirement.
165
1
            unsafe {
166
1
                #global_type::get_instance_proc_addr(instance, p_name)
167
1
            }
168
1
        }
169
1
170
1
        #[doc = "# Safety"]
171
1
        #[doc = ""]
172
1
        #[doc = "See valid usage of `vkGetDeviceProcAddr` at "]
173
1
        #[doc = "<https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetDeviceProcAddr.html>"]
174
1
        #[deny(unsafe_op_in_unsafe_fn)]
175
1
        #[no_mangle]
176
1
        pub unsafe extern "system" fn vkGetDeviceProcAddr(
177
1
            device: ::ash::vk::Device,
178
1
            p_name: *const ::std::ffi::c_char,
179
1
        ) -> ::ash::vk::PFN_vkVoidFunction {
180
1
            // Safe, because the caller is supposed to follow the exact same safety requirement.
181
1
            unsafe {
182
1
                #global_type::get_device_proc_addr(device, p_name)
183
1
            }
184
1
        }
185
1
    })
186
1
}